//go:build (386 && !appengine) || (amd64 && !appengine) || (arm && !appengine) || (arm64 && !appengine) || (ppc64le && !appengine) || (mipsle && !appengine) || (mips64le && !appengine) || (mips64p32le && !appengine) || (wasm && !appengine)
// +build 386,!appengine amd64,!appengine arm,!appengine arm64,!appengine ppc64le,!appengine mipsle,!appengine mips64le,!appengine mips64p32le,!appengine wasm,!appengine

package roaring

import (
	
	
	
	
	
	
)

func ( *arrayContainer) ( io.Writer) (int, error) {
	 := uint16SliceAsByteSlice(.content)
	return .Write()
}

func ( *bitmapContainer) ( io.Writer) (int, error) {
	if .cardinality <= arrayDefaultMaxSize {
		return 0, errors.New("refusing to write bitmap container with cardinality of array container")
	}
	 := uint64SliceAsByteSlice(.bitmap)
	return .Write()
}

func uint64SliceAsByteSlice( []uint64) []byte {
	// make a new slice header
	 := *(*reflect.SliceHeader)(unsafe.Pointer(&))

	// update its capacity and length
	.Len *= 8
	.Cap *= 8

	// instantiate result and use KeepAlive so data isn't unmapped.
	 := *(*[]byte)(unsafe.Pointer(&))
	runtime.KeepAlive(&)

	// return it
	return 
}

func uint16SliceAsByteSlice( []uint16) []byte {
	// make a new slice header
	 := *(*reflect.SliceHeader)(unsafe.Pointer(&))

	// update its capacity and length
	.Len *= 2
	.Cap *= 2

	// instantiate result and use KeepAlive so data isn't unmapped.
	 := *(*[]byte)(unsafe.Pointer(&))
	runtime.KeepAlive(&)

	// return it
	return 
}

func interval16SliceAsByteSlice( []interval16) []byte {
	// make a new slice header
	 := *(*reflect.SliceHeader)(unsafe.Pointer(&))

	// update its capacity and length
	.Len *= 4
	.Cap *= 4

	// instantiate result and use KeepAlive so data isn't unmapped.
	 := *(*[]byte)(unsafe.Pointer(&))
	runtime.KeepAlive(&)

	// return it
	return 
}

func ( *bitmapContainer) () []byte {
	return uint64SliceAsByteSlice(.bitmap)
}

// Deserialization code follows

// //
// These methods (byteSliceAsUint16Slice,...) do not make copies,
// they are pointer-based (unsafe). The caller is responsible to
// ensure that the input slice does not get garbage collected, deleted
// or modified while you hold the returned slince.
// //
func byteSliceAsUint16Slice( []byte) ( []uint16) { // here we create a new slice holder
	if len()%2 != 0 {
		panic("Slice size should be divisible by 2")
	}
	// reference: https://go101.org/article/unsafe.html

	// make a new slice header
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))

	// transfer the data from the given slice to a new variable (our result)
	.Data = .Data
	.Len = .Len / 2
	.Cap = .Cap / 2

	// instantiate result and use KeepAlive so data isn't unmapped.
	runtime.KeepAlive(&) // it is still crucial, GC can free it)

	// return result
	return
}

func byteSliceAsUint64Slice( []byte) ( []uint64) {
	if len()%8 != 0 {
		panic("Slice size should be divisible by 8")
	}
	// reference: https://go101.org/article/unsafe.html

	// make a new slice header
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))

	// transfer the data from the given slice to a new variable (our result)
	.Data = .Data
	.Len = .Len / 8
	.Cap = .Cap / 8

	// instantiate result and use KeepAlive so data isn't unmapped.
	runtime.KeepAlive(&) // it is still crucial, GC can free it)

	// return result
	return
}

func byteSliceAsInterval16Slice( []byte) ( []interval16) {
	if len()%4 != 0 {
		panic("Slice size should be divisible by 4")
	}
	// reference: https://go101.org/article/unsafe.html

	// make a new slice header
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))

	// transfer the data from the given slice to a new variable (our result)
	.Data = .Data
	.Len = .Len / 4
	.Cap = .Cap / 4

	// instantiate result and use KeepAlive so data isn't unmapped.
	runtime.KeepAlive(&) // it is still crucial, GC can free it)

	// return result
	return
}

func byteSliceAsContainerSlice( []byte) ( []container) {
	var  container
	 := int(unsafe.Sizeof())

	if len()% != 0 {
		panic("Slice size should be divisible by unsafe.Sizeof(container)")
	}
	// reference: https://go101.org/article/unsafe.html

	// make a new slice header
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))

	// transfer the data from the given slice to a new variable (our result)
	.Data = .Data
	.Len = .Len / 
	.Cap = .Cap / 

	// instantiate result and use KeepAlive so data isn't unmapped.
	runtime.KeepAlive(&) // it is still crucial, GC can free it)

	// return result
	return
}

func byteSliceAsBitsetSlice( []byte) ( []bitmapContainer) {
	 := int(unsafe.Sizeof(bitmapContainer{}))
	if len()% != 0 {
		panic("Slice size should be divisible by unsafe.Sizeof(bitmapContainer)")
	}
	// reference: https://go101.org/article/unsafe.html

	// make a new slice header
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))

	// transfer the data from the given slice to a new variable (our result)
	.Data = .Data
	.Len = .Len / 
	.Cap = .Cap / 

	// instantiate result and use KeepAlive so data isn't unmapped.
	runtime.KeepAlive(&) // it is still crucial, GC can free it)

	// return result
	return
}

func byteSliceAsArraySlice( []byte) ( []arrayContainer) {
	 := int(unsafe.Sizeof(arrayContainer{}))
	if len()% != 0 {
		panic("Slice size should be divisible by unsafe.Sizeof(arrayContainer)")
	}
	// reference: https://go101.org/article/unsafe.html

	// make a new slice header
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))

	// transfer the data from the given slice to a new variable (our result)
	.Data = .Data
	.Len = .Len / 
	.Cap = .Cap / 

	// instantiate result and use KeepAlive so data isn't unmapped.
	runtime.KeepAlive(&) // it is still crucial, GC can free it)

	// return result
	return
}

func byteSliceAsRun16Slice( []byte) ( []runContainer16) {
	 := int(unsafe.Sizeof(runContainer16{}))
	if len()% != 0 {
		panic("Slice size should be divisible by unsafe.Sizeof(runContainer16)")
	}
	// reference: https://go101.org/article/unsafe.html

	// make a new slice header
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))

	// transfer the data from the given slice to a new variable (our result)
	.Data = .Data
	.Len = .Len / 
	.Cap = .Cap / 

	// instantiate result and use KeepAlive so data isn't unmapped.
	runtime.KeepAlive(&) // it is still crucial, GC can free it)

	// return result
	return
}

func byteSliceAsBoolSlice( []byte) ( []bool) {
	 := int(unsafe.Sizeof(true))
	if len()% != 0 {
		panic("Slice size should be divisible by unsafe.Sizeof(bool)")
	}
	// reference: https://go101.org/article/unsafe.html

	// make a new slice header
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))
	 := (*reflect.SliceHeader)(unsafe.Pointer(&))

	// transfer the data from the given slice to a new variable (our result)
	.Data = .Data
	.Len = .Len / 
	.Cap = .Cap / 

	// instantiate result and use KeepAlive so data isn't unmapped.
	runtime.KeepAlive(&) // it is still crucial, GC can free it)

	// return result
	return
}

// FrozenView creates a static view of a serialized bitmap stored in buf.
// It uses CRoaring's frozen bitmap format.
//
// The format specification is available here:
// https://github.com/RoaringBitmap/CRoaring/blob/2c867e9f9c9e2a3a7032791f94c4c7ae3013f6e0/src/roaring.c#L2756-L2783
//
// The provided byte array (buf) is expected to be a constant.
// The function makes the best effort attempt not to copy data.
// Only little endian is supported. The function will err if it detects a big
// endian serialized file.
// You should take care not to modify buff as it will likely result in
// unexpected program behavior.
// If said buffer comes from a memory map, it's advisable to give it read
// only permissions, either at creation or by calling Mprotect from the
// golang.org/x/sys/unix package.
//
// Resulting bitmaps are effectively immutable in the following sense:
// a copy-on-write marker is used so that when you modify the resulting
// bitmap, copies of selected data (containers) are made.
// You should *not* change the copy-on-write status of the resulting
// bitmaps (SetCopyOnWrite).
//
// If buf becomes unavailable, then a bitmap created with
// FromBuffer would be effectively broken. Furthermore, any
// bitmap derived from this bitmap (e.g., via Or, And) might
// also be broken. Thus, before making buf unavailable, you should
// call CloneCopyOnWriteContainers on all such bitmaps.
func ( *Bitmap) ( []byte) error {
	return .highlowcontainer.frozenView()
}

/* Verbatim specification from CRoaring.
 *
 * FROZEN SERIALIZATION FORMAT DESCRIPTION
 *
 * -- (beginning must be aligned by 32 bytes) --
 * <bitset_data> uint64_t[BITSET_CONTAINER_SIZE_IN_WORDS * num_bitset_containers]
 * <run_data>    rle16_t[total number of rle elements in all run containers]
 * <array_data>  uint16_t[total number of array elements in all array containers]
 * <keys>        uint16_t[num_containers]
 * <counts>      uint16_t[num_containers]
 * <typecodes>   uint8_t[num_containers]
 * <header>      uint32_t
 *
 * <header> is a 4-byte value which is a bit union of frozenCookie (15 bits)
 * and the number of containers (17 bits).
 *
 * <counts> stores number of elements for every container.
 * Its meaning depends on container type.
 * For array and bitset containers, this value is the container cardinality minus one.
 * For run container, it is the number of rle_t elements (n_runs).
 *
 * <bitset_data>,<array_data>,<run_data> are flat arrays of elements of
 * all containers of respective type.
 *
 * <*_data> and <keys> are kept close together because they are not accessed
 * during deserilization. This may reduce IO in case of large mmaped bitmaps.
 * All members have their native alignments during deserilization except <header>,
 * which is not guaranteed to be aligned by 4 bytes.
 */
const frozenCookie = 13766

var (
	// ErrFrozenBitmapInvalidCookie is returned when the header does not contain the frozenCookie.
	ErrFrozenBitmapInvalidCookie = errors.New("header does not contain the frozenCookie")
	// ErrFrozenBitmapBigEndian is returned when the header is big endian.
	ErrFrozenBitmapBigEndian = errors.New("loading big endian frozen bitmaps is not supported")
	// ErrFrozenBitmapIncomplete is returned when the buffer is too small to contain a frozen bitmap.
	ErrFrozenBitmapIncomplete = errors.New("input buffer too small to contain a frozen bitmap")
	// ErrFrozenBitmapOverpopulated is returned when the number of containers is too large.
	ErrFrozenBitmapOverpopulated = errors.New("too many containers")
	// ErrFrozenBitmapUnexpectedData is returned when the buffer contains unexpected data.
	ErrFrozenBitmapUnexpectedData = errors.New("spurious data in input")
	// ErrFrozenBitmapInvalidTypecode is returned when the typecode is invalid.
	ErrFrozenBitmapInvalidTypecode = errors.New("unrecognized typecode")
	// ErrFrozenBitmapBufferTooSmall is returned when the buffer is too small.
	ErrFrozenBitmapBufferTooSmall = errors.New("buffer too small")
)

func ( *roaringArray) ( []byte) error {
	if len() < 4 {
		return ErrFrozenBitmapIncomplete
	}

	 := binary.BigEndian.Uint32([len()-4:])
	if &0x7fff == frozenCookie {
		return ErrFrozenBitmapBigEndian
	}

	 := binary.LittleEndian.Uint32([len()-4:])
	 = [:len()-4]

	if &0x7fff != frozenCookie {
		return ErrFrozenBitmapInvalidCookie
	}

	 := int( >> 15)
	if  > (1 << 16) {
		return ErrFrozenBitmapOverpopulated
	}

	// 1 byte per type, 2 bytes per key, 2 bytes per count.
	if len() < 5* {
		return ErrFrozenBitmapIncomplete
	}

	 := [len()-:]
	 = [:len()-]

	 := byteSliceAsUint16Slice([len()-2*:])
	 = [:len()-2*]

	 := byteSliceAsUint16Slice([len()-2*:])
	 = [:len()-2*]

	, ,  := 0, 0, 0
	,  := 0, 0
	for ,  := range  {
		switch  {
		case 1:
			++
		case 2:
			++
			 += int([]) + 1
		case 3:
			++
			 += int([])
		default:
			return ErrFrozenBitmapInvalidTypecode
		}
	}

	if len() < (1<<13)*+4*+2* {
		return ErrFrozenBitmapIncomplete
	}

	 := byteSliceAsUint64Slice([:(1<<13)*])
	 = [(1<<13)*:]

	 := byteSliceAsInterval16Slice([:4*])
	 = [4*:]

	 := byteSliceAsUint16Slice([:2*])
	 = [2*:]

	if len() != 0 {
		return ErrFrozenBitmapUnexpectedData
	}

	var  container
	 := int(unsafe.Sizeof()) * 
	 := int(unsafe.Sizeof(bitmapContainer{})) * 
	 := int(unsafe.Sizeof(arrayContainer{})) * 
	 := int(unsafe.Sizeof(runContainer16{})) * 
	 := int(unsafe.Sizeof(true)) * 

	 :=  +  +  +  + 
	 := make([]byte, )

	 := byteSliceAsContainerSlice([:])
	 = [:]

	 := byteSliceAsBitsetSlice([:])
	 = [:]

	 := byteSliceAsArraySlice([:])
	 = [:]

	 := byteSliceAsRun16Slice([:])
	 = [:]

	 := byteSliceAsBoolSlice()

	, ,  := 0, 0, 0
	for ,  := range  {
		[] = true

		switch  {
		case 1:
			[] = &[]
			[].cardinality = int([]) + 1
			[].bitmap = [:1024]
			 = [1024:]
			++
		case 2:
			[] = &[]
			 := int([]) + 1
			[].content = [:]
			 = [:]
			++
		case 3:
			[] = &[]
			[].iv = [:[]]
			 = [[]:]
			++
		}
	}

	// Not consuming the full input is a bug.
	if  !=  || len() != 0 ||
		 !=  || len() != 0 ||
		 !=  || len() != 0 {
		panic("we missed something")
	}

	.keys = 
	.containers = 
	.needCopyOnWrite = 
	.copyOnWrite = true

	return nil
}

// GetFrozenSizeInBytes returns the size in bytes of the frozen bitmap.
func ( *Bitmap) () uint64 {
	, ,  := uint64(0), uint64(0), uint64(0)
	for ,  := range .highlowcontainer.containers {
		switch v := .(type) {
		case *bitmapContainer:
			++
		case *arrayContainer:
			 += uint64(len(.content))
		case *runContainer16:
			 += uint64(len(.iv))
		}
	}
	return 4 + 5*uint64(len(.highlowcontainer.containers)) +
		( << 13) + 2* + 4*
}

// Freeze serializes the bitmap in the CRoaring's frozen format.
func ( *Bitmap) () ([]byte, error) {
	 := .GetFrozenSizeInBytes()
	 := make([]byte, )
	,  := .FreezeTo()
	return , 
}

// FreezeTo serializes the bitmap in the CRoaring's frozen format.
func ( *Bitmap) ( []byte) (int, error) {
	 := .highlowcontainer.containers
	 := len()

	, ,  := 0, 0, 0
	for ,  := range  {
		switch v := .(type) {
		case *bitmapContainer:
			++
		case *arrayContainer:
			 += len(.content)
		case *runContainer16:
			 += len(.iv)
		}
	}

	 := 4 + 5* + (1<<13)* + 4* + 2*
	if len() <  {
		return 0, ErrFrozenBitmapBufferTooSmall
	}

	 := byteSliceAsUint64Slice([:(1<<13)*])
	 = [(1<<13)*:]

	 := byteSliceAsInterval16Slice([:4*])
	 = [4*:]

	 := byteSliceAsUint16Slice([:2*])
	 = [2*:]

	 := byteSliceAsUint16Slice([:2*])
	 = [2*:]

	 := byteSliceAsUint16Slice([:2*])
	 = [2*:]

	 := [:]
	 = [:]

	 := uint32(frozenCookie | ( << 15))
	binary.LittleEndian.PutUint32([:4], )

	copy(, .highlowcontainer.keys[:])

	for ,  := range  {
		switch v := .(type) {
		case *bitmapContainer:
			copy(, .bitmap)
			 = [1024:]
			[] = uint16(.cardinality - 1)
			[] = 1
		case *arrayContainer:
			copy(, .content)
			 = [len(.content):]
			 := len(.content)
			[] = uint16( - 1)
			[] = 2
		case *runContainer16:
			copy(, .iv)
			 := len(.iv)
			 = [:]
			[] = uint16()
			[] = 3
		}
	}

	return , nil
}

// WriteFrozenTo serializes the bitmap in the CRoaring's frozen format.
func ( *Bitmap) ( io.Writer) (int, error) {
	// FIXME: this is a naive version that iterates 4 times through the
	// containers and allocates 3*len(containers) bytes; it's quite likely
	// it can be done more efficiently.
	 := .highlowcontainer.containers
	 := 0

	for ,  := range  {
		,  := .(*bitmapContainer)
		if ! {
			continue
		}
		,  := .Write(uint64SliceAsByteSlice(.bitmap))
		 += 
		if  != nil {
			return , 
		}
	}

	for ,  := range  {
		,  := .(*runContainer16)
		if ! {
			continue
		}
		,  := .Write(interval16SliceAsByteSlice(.iv))
		 += 
		if  != nil {
			return , 
		}
	}

	for ,  := range  {
		,  := .(*arrayContainer)
		if ! {
			continue
		}
		,  := .Write(uint16SliceAsByteSlice(.content))
		 += 
		if  != nil {
			return , 
		}
	}

	,  := .Write(uint16SliceAsByteSlice(.highlowcontainer.keys))
	 += 
	if  != nil {
		return , 
	}

	 := make([]byte, 3*len())
	 := byteSliceAsUint16Slice([:2*len()])
	 := [2*len():]

	for ,  := range  {
		switch c := .(type) {
		case *bitmapContainer:
			[] = uint16(.cardinality - 1)
			[] = 1
		case *arrayContainer:
			 := len(.content)
			[] = uint16( - 1)
			[] = 2
		case *runContainer16:
			 := len(.iv)
			[] = uint16()
			[] = 3
		}
	}

	,  = .Write()
	 += 
	if  != nil {
		return , 
	}

	 := uint32(frozenCookie | (len() << 15))
	if  := binary.Write(, binary.LittleEndian, );  != nil {
		return , 
	}
	 += 4

	return , nil
}